﻿using System;
using System.Linq;
using System.Net;
using System.Text;

namespace oModbus.Utility
{
    /// <summary>
    /// 转换扩展
    /// </summary>
    public static class ConvertExtend
    {

        /// <summary>
        ///将四UIT16值转换为IEEE 64浮点格式。
        /// </summary>
        /// <param name="b3">高</param>
        /// <param name="b2"></param>
        /// <param name="b1"></param>
        /// <param name="b0">低</param>
        /// <returns></returns>
        public static double GetDouble(ushort b3, ushort b2, ushort b1, ushort b0)
        {
            byte[] value = BitConverter.GetBytes(b0)
                .Concat(BitConverter.GetBytes(b1))
                .Concat(BitConverter.GetBytes(b2))
                .Concat(BitConverter.GetBytes(b3))
                .ToArray();

            return BitConverter.ToDouble(value, 0);
        }

        /// <summary>
        ///将两个UTIT16值转换成IEEE 32浮点格式。
        /// </summary>
        /// <param name="highOrderValue">高</param>
        /// <param name="lowOrderValue">低</param>
        /// <returns></returns>
        public static float GetSingle(ushort highOrderValue, ushort lowOrderValue)
        {
            byte[] value = BitConverter.GetBytes(lowOrderValue)
                .Concat(BitConverter.GetBytes(highOrderValue))
                .ToArray();

            return BitConverter.ToSingle(value, 0);
        }
        /// <summary>
        ///   int 转2位 Uint16
        /// </summary>
        /// <param name="numbers"></param>
        /// <returns></returns>
        public static byte[] GetBytes(this ushort numbers)
        {
            byte[] result = new byte[2];
            byte[] value = BitConverter.GetBytes(numbers);
            result[0] = value[1];
            result[1] = value[0];
            return result;
        }
        /// <summary>
        ///   int 转2位 Uint16
        /// </summary> 
        /// <returns></returns>
        public static ushort GetUint16(byte highOrderValue, byte lowOrderValue)
        {
            byte[] value = {lowOrderValue, highOrderValue };
            return BitConverter.ToUInt16(value, 0);
        }
        /// <summary>
        /// 将两个UTIT16值转换为UIT32。
        /// </summary>
        public static uint GetUInt32(ushort highOrderValue, ushort lowOrderValue)
        {
            byte[] value = BitConverter.GetBytes(lowOrderValue)
                .Concat(BitConverter.GetBytes(highOrderValue))
                .ToArray();

            return BitConverter.ToUInt32(value, 0);
        }

        /// <summary>
        ///   将字节数组转换为ASCII字节数组。
        /// </summary>
        /// <param name="numbers"></param>
        /// <returns></returns>
        public static byte[] GetAsciiBytes(params byte[] numbers)
        {
            return Encoding.UTF8.GetBytes(numbers.SelectMany(n => n.ToString("X2")).ToArray());
        }

        /// <summary>
        ///将UIT16数组转换为ASCII字节数组。
        /// </summary>
        /// <param name="numbers">UIT16</param>
        /// <returns>ASCII</returns>
        public static byte[] GetAsciiBytes(params ushort[] numbers)
        {
            return Encoding.UTF8.GetBytes(numbers.SelectMany(n => n.ToString("X4")).ToArray());
        }
        /// <summary>
        ///   将字节数组转换为ASCII字节数组。
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static byte[] GetBytes(this string str)
        {
            return Encoding.UTF8.GetBytes(str).ToArray();
        }
        ///// <summary>
        /////    将网络顺序字节数组转换为主机顺序的
        ///// </summary>
        ///// <param name="networkBytes"></param>
        ///// <returns></returns>
        //public static ushort[] NetworkBytesToHostUInt16(this byte[] networkBytes)
        //{
        //    if (networkBytes == null)
        //    {
        //        throw new ArgumentNullException(nameof(networkBytes));
        //    }

        //    if (networkBytes.Length % 2 != 0)
        //    {
        //        throw new FormatException("Hex string must have even number of characters.");
        //    }

        //    ushort[] result = new ushort[networkBytes.Length / 2];

        //    for (int i = 0; i < result.Length; i++)
        //    {
        //        result[i] = (ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(networkBytes, i * 2));
        //    }

        //    return result;
        //}

        /// <summary>
        /// 将十六进制字符串转换为字节数组
        /// </summary>
        /// <param name="hex"> hex</param>
        /// <returns>bytes</returns>
        public static byte[] HexToBytes(string hex)
        {
            if (hex == null)
            {
                throw new ArgumentNullException(nameof(hex));
            }

            if (hex.Length % 2 != 0)
            {
                throw new FormatException("Hex string must have even number of characters.");
            }

            byte[] bytes = new byte[hex.Length / 2];

            for (int i = 0; i < bytes.Length; i++)
            {
                bytes[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
            }

            return bytes;
        }

        /// <summary>
        /// 把指定的二进制值显示为适合记入日志的文本串
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static string GetHexString(this byte[] data)
        {
            if (data == null) return "";
            string result = "";
            int start = 0;
            while (start < data.Length)
            {
                if (!result.Equals("")) result += "\r\n";
                int len = data.Length - start;
                if (len > 16) len = 16;
                string strByte = BitConverter.ToString(data, start, len);
                strByte = strByte.Replace('-', ' ');
                if (len > 8)
                {
                    strByte = strByte.Substring(0, 23) + " " + strByte.Substring(24);
                }
                if (len < 16)
                {
                    strByte += new string(' ', (16 - len) * 3);
                }
                strByte += "  ";
                for (int i = 0; i < len; i++)
                {
                    char c = Convert.ToChar(data[start + i]);
                    if (char.IsControl(c))
                    {
                        c = '.';
                    }
                    strByte += c;
                }
                result += strByte;
                start += len;
            }
            return result;
        }

        public static string GetString(this byte[] data)
        {
            return Encoding.UTF8.GetString(data);
        }
    }
}
